package sicnu.cs.ich.user.rest;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.web.bind.annotation.*;
import sicnu.cs.ich.api.common.ResultInfo;
import sicnu.cs.ich.api.domain.vo.Auth;
import sicnu.cs.ich.common.util.ResultInfoUtil;
import sicnu.cs.ich.common.util.keyCryptor.RSAUtil;
import sicnu.cs.ich.security.util.JwtUtil;
import sicnu.cs.ich.user.service.IEncryptKey;

import javax.crypto.BadPaddingException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

/**
 * @author CaiKe
 * @date 2021/11/3 16:01
 */
@Slf4j
@RestController
@RequestMapping("/auth/secure")
@RequiredArgsConstructor
@Api(tags = {"AUTH-用于安全相关"})
public class AuthResource {
    private final IEncryptKey encryptKey;
    private final JwtUtil jwtUtil;

    @GetMapping("/public")
    @ApiOperation(value = "获得后台RSA公钥")
    public ResultInfo<String> getPublicKey() {
        // 给前台 后台公钥
        final String[] keys = encryptKey.generateRSAKeys();
        return ResultInfoUtil.buildSuccessWithStr(keys[0]);
    }

    @GetMapping("/symmetry")
    @ApiOperation(value = "获得加密后的AES密钥")
    public ResultInfo<String> getSymmetryKey(@RequestParam("key") String key) throws InvalidKeySpecException, NoSuchAlgorithmException, BadPaddingException {
        // 前台传回用 后台公钥 加密的 前台公钥。后台进行解密，然后用前台公钥加密 后台对称密钥。至此结束
        key = key.replace(" ", "+");
        final String[] keys = encryptKey.generateRSAKeys();
        String fePublicKey = RSAUtil.privateDecrypt(key, RSAUtil.getPrivateKey(keys[1]));
        String encodedSecretKey = RSAUtil.publicEncrypt(encryptKey.generateAESKey(), RSAUtil.getPublicKey(fePublicKey));
        return ResultInfoUtil.buildSuccessWithStr(encodedSecretKey);
    }

    /**
     * 通过RefreshToken返回AccessToken以及Token有效时间
     */
    @PostMapping("/refresh")
    @ApiOperation("刷新token")
    public ResultInfo<Auth> refreshToken(@RequestBody Auth auth) {
        String refreshToken = auth.getRefreshToken();
        String accessToken = auth.getToken();
        if (!jwtUtil.validateRefreshToken(refreshToken) && !jwtUtil.validateWithoutExpiration(accessToken)) {
            throw new BadCredentialsException("凭证无效！");
        }
        return ResultInfoUtil.buildSuccess(jwtUtil.buildAccessTokenWithRefreshToken(refreshToken));
    }



}